﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using AFSharedLibrary;
using SharedClasses;
using AFSharedLibrary.SharedControls;
using UIDesigner.FieldHandlers;
using UIDesigner.FieldHandlers.Bases;
using System.Diagnostics;
using UIDesigner.ControlProviders.Bases;

namespace UIDesigner.Designers.Forms
{
    public partial class frmFieldSpecifications : Form
    {
        private Dictionary<string, FieldSpecification> m_rgSpecifications;
        private DataGridViewCell m_ctrlEditCell;
        private int m_hWndFound;
        private bool m_bCodeChange;
        private LayoutManager m_objLayoutManager;
        private Construct m_objConstruct;

        public Construct Construct
        {
            set
            {
                m_objConstruct = value;
            }
        }

        public Dictionary<string, FieldSpecification> Specifications
        {
            set 
            { 
                m_rgSpecifications = value; 
            }
        }

        public frmFieldSpecifications()
        {
            InitializeComponent();

            FieldSpecsGrid.Columns.Add(new ControlConfigColumn());
            m_objLayoutManager = new LayoutManager(this.PreviewPanel);
        }

        private FieldSpecifications GridDataSource
        {
            get
            {
                FieldSpecifications rgSpecs = new FieldSpecifications();

                foreach (FieldSpecification objSpec in m_rgSpecifications.Values)
                {
                    objSpec.ClearSelection();
                    rgSpecs.Add(objSpec);
                }

                return rgSpecs;
            }
        }

        private void frmFieldSpecifications_Load(object sender, EventArgs e)
        {
            Cursor.Current = Cursors.WaitCursor;

            this.Text = "Field Specifications - " + m_objConstruct.Name; 

            FieldSpecsGrid.AutoGenerateColumns = false;
            FieldSpecsGrid.DataSource = this.GridDataSource;

            m_objLayoutManager = new LayoutManager(PreviewPanel);

            Cursor.Current = Cursors.Default;
        }

        private void cmdOK_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
            this.Close();
        }

        private void cmdCancel_Click(object sender, EventArgs e)
        {
            foreach (FieldSpecification objSpec in m_rgSpecifications.Values)
            {
                objSpec.Revert();
            }

            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }

        private void FieldSpecsGrid_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            m_ctrlEditCell = FieldSpecsGrid[e.ColumnIndex, e.RowIndex];

            EditTimer.Start();
        }

        private void EditTimer_Tick(object sender, EventArgs e)
        {
            int hWndEdit;
            int nLoop = 0;
            WindowsAPI.RECT rc = new WindowsAPI.RECT();

            EditTimer.Stop();
            hWndEdit = FindEditControl(this.Handle.ToInt32());

            while (hWndEdit == 0)
            {
                Application.DoEvents();
                hWndEdit = FindEditControl(this.Handle.ToInt32());

                nLoop++;

                if (nLoop > 10000)
                {
                    return;
                }
            }

            if (hWndEdit != 0)
            {
                int hParent;

                WindowsAPI.GetWindowRect(hWndEdit, ref rc);
                hParent = WindowsAPI.GetParent(hWndEdit);

                WindowsAPI.DestroyWindow(hWndEdit);

                ControlUtils.ScreenToClient(this.SplitContainer.Panel1.Handle.ToInt32(), ref rc);

                cboControlOptions.Location = new Point(rc.Left - 3, rc.Top - 4);
                cboControlOptions.Size = new Size(RectMath.Width(rc) + 4, RectMath.Height(rc) + 2);

                cboControlOptions.Visible = true;

                FieldSpecification objSpec = (FieldSpecification)this.GridDataSource[m_ctrlEditCell.RowIndex];

                m_bCodeChange = true;

                cboControlOptions.DataSource = objSpec.ControlOptions;
                cboControlOptions.DisplayMember = "OptionName";
                cboControlOptions.ValueMember = "OptionName";

                if (objSpec.SelectedOption != null)
                {
                    cboControlOptions.SelectedIndex = cboControlOptions.FindString(objSpec.SelectedOption.OptionName);
                }
                else
                {
                    cboControlOptions.SelectedIndex = -1;
                }

                m_bCodeChange = false;
            }
        }

        private int FindEditControl(int hWnd)
        {
            IntPtr nParam = new IntPtr(0);

            WindowsAPI.EnumChildWindows(hWnd, new WindowsAPI.EnumChildProc(EnumChildProc), ref nParam);

            return m_hWndFound;
        }

        private int EnumChildProc(int hwnd, ref IntPtr lParam)
        {
            string strEditClassPrefix = "WindowsForms10.EDIT";
            StringBuilder objClass = new StringBuilder(255);
            string strClass;

            WindowsAPI.GetClassName(hwnd, objClass, 255);
            strClass = objClass.ToString();

            if (strClass.StartsWith(strEditClassPrefix))
            {
                m_hWndFound = hwnd;
                return 0;
            }
            else
            {
                FindEditControl(hwnd);
                return 1;
            }
        }

        private void HideDropdown()
        {
            cboControlOptions.Hide();
        }

        private void FieldSpecsGrid_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (m_ctrlEditCell != null)
            {
                if (!(e.ColumnIndex == m_ctrlEditCell.ColumnIndex && e.RowIndex == m_ctrlEditCell.RowIndex))
                {
                    cboControlOptions.Hide();
                }
            }
        }

        private void cboControlOptions_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!m_bCodeChange)
            {
                FieldSpecification objSpec = (FieldSpecification)this.GridDataSource[m_ctrlEditCell.RowIndex];
                ControlOption objOption = (ControlOption)cboControlOptions.SelectedItem;

                objSpec.SelectedOption = objOption;

                FieldSpecsGrid_RowEnter(cboControlOptions, new DataGridViewCellEventArgs(0, m_ctrlEditCell.RowIndex));
            }
        }

        private void cboControlOptions_TextUpdate(object sender, EventArgs e)
        {
            string strText = cboControlOptions.Text;

            foreach (ControlOption objOption in cboControlOptions.Items)
            {
                if (objOption.OptionName.StartsWith(strText))
                {
                    cboControlOptions.SelectedIndex = cboControlOptions.FindString(objOption.OptionName);
                    cboControlOptions.SelectionStart = strText.Length;
                    cboControlOptions.SelectionLength = objOption.OptionName.Length;

                    return;
                }
            }
        }

        private void DrawPreview(FieldSpecification objSpec)
        {
            if (objSpec.SelectedOption == null)
            {
                PreviewPanel.Controls.Clear();
            }
            else
            {
                IFieldHandler objHandler = objSpec.SelectedOption.FieldHandler;
                string strOption = objSpec.SelectedOption.OptionName;
                int nTabIndex = 0;
                LayoutStyle eLayoutStyle;
                int nAlignment;
                List<char> rgMnemonics = new List<char>();
                LayoutItem objLayoutItem;
                Size szControl;

                m_objLayoutManager.Clear();

                objHandler.NegotiateLayout(strOption, PreviewPanel, objSpec.Member, LayoutMode.TableLayout, ref nTabIndex, out eLayoutStyle, out nAlignment, out szControl);

                Debug.Assert(eLayoutStyle != LayoutStyle.Unassigned);
                Debug.Assert(nAlignment != -1);

                objLayoutItem = m_objLayoutManager.AddRow(eLayoutStyle, nAlignment, true);

                objHandler.AddPreviewControls(strOption, objLayoutItem.InnerPanel, objSpec.Member, nTabIndex, objLayoutItem.TableLayoutPanelCellPositions, rgMnemonics);
            }
        }

        private void FieldSpecsGrid_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            FieldSpecification objSpec = (FieldSpecification) this.GridDataSource[e.RowIndex];

            DrawPreview(objSpec);
        }

        private void FieldSpecsGrid_Scroll(object sender, ScrollEventArgs e)
        {
            cboControlOptions.Hide();
        }

        private void frmFieldSpecifications_Resize(object sender, EventArgs e)
        {
            HideDropdown();
        }

        private void frmFieldSpecifications_ResizeBegin(object sender, EventArgs e)
        {
            HideDropdown();
        }

        private void FieldSpecsGrid_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
        {
            HideDropdown();
        }
    }
}
